package com.jule.teenpatti.game.network.protocol.reqs;

import JoloProtobuf.GameSvr.JoloGame;
import com.jule.core.common.log.LoggerUtils;
import com.jule.teenpatti.base.enums.ErrorCodeEnum;
import com.jule.teenpatti.base.enums.GameConst;
import com.jule.teenpatti.base.enums.TableStateEnum;
import com.jule.teenpatti.game.config.Config;
import com.jule.teenpatti.game.gameUtil.GameLogic;
import com.jule.teenpatti.game.model.PlayerInfo;
import com.jule.teenpatti.game.model.eenum.NextBetPlayerReasonEnum;
import com.jule.teenpatti.game.model.eenum.PlayTypeEnum;
import com.jule.teenpatti.game.model.eenum.PlayerStateEnum;
import com.jule.teenpatti.game.network.protocol.ClientReq;
import com.jule.teenpatti.game.network.protocol.acks.JoloGame_ApplyFoldAck_50012;
import com.jule.teenpatti.game.play.AbstractTable;
import com.jule.teenpatti.game.service.TableService;
import com.jule.teenpatti.game.utils.log.TableLogUtil;
import com.jule.teenpatti.game.vavle.notice.NoticeBroadcastMessages;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JoloGame_ApplyFoldReq_50012 extends ClientReq {
    private long time;
    private final static Logger logger = LoggerFactory.getLogger(JoloGame_ApplyFoldReq_50012.class);

    public JoloGame_ApplyFoldReq_50012(int functionId) {
        super(functionId);
    }

    private JoloGame.JoloGame_ApplyFoldReq req;


    @Override
    public void readPayLoadImpl(ByteBuf buf) throws Exception {
        time = System.currentTimeMillis();
        byte[] blob = new byte[buf.readableBytes()];
        buf.readBytes(blob);
        req = JoloGame.JoloGame_ApplyFoldReq.parseFrom(blob);
        AbstractTable table = TableService.getInstance().getTable(header.gameId + "", req.getRoomId(), req.getTableId());
        if (null != table) {
            this.setTable(table);
        } else {
            logger.error("桌子不存在,roomId->" + req.getRoomId() + ", tableId->" + req.getTableId());
        }
    }

    @Override
    public void processImpl() throws Exception {
        logger.debug("收到消息-> " + functionId + " reqNum-> " + header.reqNum + "msg ->" + req.toString());
        //初始化信息
        String userId = req.getUserId();
        String roomId = req.getRoomId();
        String tableId = req.getTableId();
        String gameOrderId = req.getGameOrderId();
        int betRoundId = req.getBetRoundId();

        AbstractTable table = null;
        JoloGame.JoloGame_ApplyFoldAck.Builder ack = JoloGame.JoloGame_ApplyFoldAck.newBuilder();
        try {
            //初始化ack返回值
            ack.setUserId(userId);
            ack.setRoomId(roomId);
            ack.setTableId(tableId);
            ack.setGameOrderId(gameOrderId);
            ack.setBetRoundId(betRoundId);

            //获得桌子信息
            table = getTable();

            //判断GameOrderId是否一致
            if (!gameOrderId.equals(table.getCurrGameOrderId())) {
                ack.setResult(-1);
                logger.error("GameOrderId不匹配, currGameOrderId->" + table.getCurrGameOrderId() + ", gameOrderId->" + gameOrderId);
                ack.setResultMsg(ErrorCodeEnum.GAME_50013_2.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyFoldAck_50012(ack.build(), header));
                return;
            }

            PlayerInfo player = table.getPlayer(userId);
            if (null == player) {
                logger.info("can't found player info, playerId->" + userId);
                ack.setResult(-2).setResultMsg(ErrorCodeEnum.GAME_50050_2.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyFoldAck_50012(ack.build(), header));
                return;
            }

            if (player.getSeatNum() <= 0) {
                logger.info("player have no seat,can't fold. playerId->" + userId);
                ack.setResult(-3).setResultMsg(ErrorCodeEnum.GAME_50014_1.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyFoldAck_50012(ack.build(), header));
                return;
            }

            //判断BetRoundId是否一致
            if (betRoundId < table.getCurrRoundId()) {
                ack.setResult(-4);
                logger.error("BetRoundId error, currGameBetRoundId->" + table.getCurrRoundId() + ", paramBetRoundId->" + betRoundId);
                ack.setResultMsg(ErrorCodeEnum.GAME_50012_2.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyFoldAck_50012(ack.build(), header));
                return;
            }

            if(table.getTableStateEnum().getValue() == TableStateEnum.OPEN_CARD.getValue()){
                ack.setResult(-5);
                logger.error("比牌中不能弃牌：{}",table.getTableStateEnum());
                ack.setResultMsg("比牌中不能弃牌");
                ctx.writeAndFlush(new JoloGame_ApplyFoldAck_50012(ack.build(), header));
                return;
            }

            //修改玩家状态
            player.setState(PlayerStateEnum.fold);

            ctx.writeAndFlush(new JoloGame_ApplyFoldAck_50012(ack
                    .setResult(1)
                    .setCurrPlayScore(player.getPlayScoreStore())
                    .setBetRoundId(table.getCurrRoundId())
                    .build(), header));

            table.setLastActionTime(System.currentTimeMillis());

            TableLogUtil.fold(functionId, "fold", userId, player.getNickName(), table.getPlayType() + "",
                    table.getRoomId(), table.getTableId(), table.getCurrGameOrderId(), betRoundId, table.getCurrRoundId());

            table.getInGamePlayers().remove(player.getSeatNum()); //将玩家从游戏中移除

            //如果玩家已看牌则修改桌内看牌玩家数量
            if (player.getIsBlind() != 1) {
                table.setSeeCardNum(table.getSeeCardNum() - 1);
            }

            PlayerInfo nextActionPlayer = table.getNextBetPlayer(player.getSeatNum(), NextBetPlayerReasonEnum.FOLD);

            if (table.getInGamePlayers().size() < 2) {//如果游戏中玩家小于二人，则直接调用结算消息
                nextActionPlayer = null;
            } else if (table.getInGamePlayers().size() == 2 && table.getSeeCardNum() == 2) { //如果本局游戏只剩两人则可以show
                nextActionPlayer.setIsCanShow(1);
            } else if (table.getInGamePlayers().size() == 2 && table.currPlayType() == PlayTypeEnum.blind.getGameId()
                    && table.getCurrRoundId() > Config.BLIND_SHOW_ROUNDCOUNT) {
                nextActionPlayer.setIsCanShow(1);
            }

            //如果弃牌的人是已看牌玩家，则重新判断当前行动玩家是否可以sideshow
//            table.setUpPlayerShowCard();

            try {
                NoticeBroadcastMessages.applyFold(table, player, nextActionPlayer);
            } catch (Exception ex) {
                logger.error("SendNotice ERROR：", ex);
            }
            if (nextActionPlayer == null) {
                GameLogic.settle(table);
            } else {
                nextActionPlayer.setState(PlayerStateEnum.beting);//设置下一个玩家为行动状态
                if (table.getInGamePlayers().size() == 2 && table.getSeeCardNum() == 2) { //如果本局游戏只剩两人则可以show
                    nextActionPlayer.setIsCanShow(1);
                }
                GameLogic.betTimer(table);//启动下一个玩家下注倒计时
            }
            long timeMillis = System.currentTimeMillis() - time;
            if (timeMillis > GameConst.COST_TIME) {
                LoggerUtils.performance.info("ApplyFoldReq_50012,cost time:{},req:{}", timeMillis, req.toString());
            }
        } catch (Exception ex) {
            logger.error("弃牌异常：userId->"+userId+", gameOrderId->"+gameOrderId+", message->"+ex.getMessage());
            ack.setResult(-6);
            ack.setResultMsg(ex.getMessage());
            ctx.writeAndFlush(new JoloGame_ApplyFoldAck_50012(ack.build(), header));
        } finally {
//            logger.debug("Fold ACK info: "+ack.toString());
//            logger.debug("Fold ACK bytes length: "+ack.build().toByteArray().length);
//            if(null != table){
//                logger.debug("All Player info: "+System.getProperty("line.separator") + table.toStringAllPlayers());
//
//                logger.debug("InGame Player info: "+System.getProperty("line.separator") + table.toStringInGamePlayers());
//            }
//            logger.debug("Fold over. Table state: "+table.getTableStateEnum());

            long useTimes = System.currentTimeMillis() - time;
            if(useTimes > 500) {
                logger.error("ApplyFold。 耗时->{} 毫秒, reqNum->{}", useTimes, header.reqNum); //TODO:临时增加
            }
        }
    }
}
